package com.atguigu.spzx.service.order.service.impl;

import cn.hutool.core.util.IdUtil;
import com.atguigu.spzx.cart.client.feign.CartFeignClient;
import com.atguigu.spzx.common.handler.exception.SpzxException;
import com.atguigu.spzx.common.handler.interceptor.SpzxAuthInterceptor;
import com.atguigu.spzx.model.common.Result;
import com.atguigu.spzx.model.common.ResultCodeEnum;
import com.atguigu.spzx.model.dto.h5.OrderSubmitDto;
import com.atguigu.spzx.model.entity.h5.*;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.vo.h5.TradeVo;
import com.atguigu.spzx.product.client.feign.ProductFeignClient;
import com.atguigu.spzx.service.order.mapper.OrderMapper;
import com.atguigu.spzx.service.order.service.OrderItemService;
import com.atguigu.spzx.service.order.service.OrderService;
import com.atguigu.spzx.user.client.feign.UserFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * title:
 * author: zgl
 * date: 2024/1/18
 * description：
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService {
    @Resource
    private CartFeignClient client;

    @Resource
    private ProductFeignClient productFeignClient;

    @Resource
    private UserFeignClient userFeignClient;

    @Resource
    private OrderItemService orderItemService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public TradeVo trade() {
        List<CartInfo> checkedList = client.getCheckedList().getData();
        TradeVo tradeVo = new TradeVo();
        List<OrderItem> orderItems = new ArrayList<>();
        Long token = IdUtil.getSnowflake(1, 1).nextId();
        stringRedisTemplate.opsForValue().set("spzx:order:idempotence" + token.toString(), "1", 1, TimeUnit.HOURS);
        for (CartInfo cartInfo : checkedList) {
            OrderItem orderItem = new OrderItem();
            orderItem.setSkuId(cartInfo.getSkuId());
            orderItem.setOrderId(token);
            orderItem.setSkuName(cartInfo.getSkuName());
            orderItem.setThumbImg(cartInfo.getImgUrl());
            orderItem.setSkuNum(cartInfo.getSkuNum());
            orderItem.setSkuPrice(cartInfo.getCartPrice());
            orderItems.add(orderItem);
        }
        BigDecimal totalMoney = new BigDecimal(0);
        for (CartInfo cartInfo : checkedList) {
            totalMoney = totalMoney.add(cartInfo.getCartPrice().multiply(new BigDecimal(cartInfo.getSkuNum())));
        }
        tradeVo.setTotalAmount(totalMoney);
        tradeVo.setOrderItemList(orderItems);
        return tradeVo;
    }


    @Override
    public Long submitOrder(OrderSubmitDto submitDto) {
        //幂等性
        //验证价格和库存
        //远程调用product服务查询productSku(skuId)
        List<OrderItem> orderItemList = submitDto.getOrderItemList();
        if (CollectionUtils.isEmpty(orderItemList)) {
            throw new SpzxException(ResultCodeEnum.FAIL);
        }
        //幂等性
        Long token = orderItemList.get(0).getOrderId();
        Boolean delete = stringRedisTemplate.delete("spzx:order:idempotence" + token.toString());
        if (!delete) {
            //删除失败
            throw new SpzxException(ResultCodeEnum.ORDER_RESUBMIT_ERROR);
        }
        orderItemList.forEach(orderItem -> {
                    Result<ProductSku> productResult = productFeignClient.getProductList(orderItem.getSkuId());
                    if (productResult.getCode() != 200) {
                        throw new SpzxException(ResultCodeEnum.FAIL);
                    }
                    ProductSku productSku = productResult.getData();
                    if (orderItem.getSkuPrice().compareTo(productSku.getSalePrice()) != 0) {
                        throw new SpzxException(ResultCodeEnum.PRODUCT_PRICE_ERROR);
                    }
                    if (productSku.getStockNum() - orderItem.getSkuNum() < 0) {
                        throw new SpzxException(ResultCodeEnum.PRODUCT_NUM_ERROR);
                    }
                }
        );
        //地址信息
        Result<UserAddress> addressResult = userFeignClient.getUserAddress(submitDto.getUserAddressId());
        if (addressResult.getCode() != 200) {
            throw new SpzxException(ResultCodeEnum.FAIL);
        }
        //保存订单和订单项
        //保存订单order_info
        UserInfo userInfo = SpzxAuthInterceptor.threadLocal.get();
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(userInfo.getId());
        orderInfo.setNickName(userInfo.getNickName());
        orderInfo.setFeightFee(submitDto.getFeightFee());
        orderInfo.setOrderStatus(0);

        UserAddress userAddress = addressResult.getData();
        orderInfo.setReceiverName(userAddress.getName());
        orderInfo.setReceiverPhone(userAddress.getPhone());
        orderInfo.setReceiverTagName(userAddress.getTagName());
        orderInfo.setReceiverProvince(userAddress.getProvinceCode());
        orderInfo.setReceiverCity(userAddress.getCityCode());
        orderInfo.setReceiverDistrict(userAddress.getDistrictCode());
        orderInfo.setReceiverAddress(userAddress.getFullAddress());
        //备注
        orderInfo.setRemark(submitDto.getRemark());
        //原价和优惠后的价格
        BigDecimal total = new BigDecimal(0);
        for (OrderItem orderItem : submitDto.getOrderItemList()) {
            total = total.add(orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum())));
        }
        orderInfo.setOriginalTotalAmount(total);
        orderInfo.setTotalAmount(total);
        //订单编号
        String orderNo = IdUtil.getSnowflake(1, 1).nextIdStr();
        orderInfo.setOrderNo(orderNo);
        this.save(orderInfo);

        //不设置
   /*     orderInfo.setPaymentTime(null);
        orderInfo.setDeliveryTime(null);
        orderInfo.setCancelTime(null);
        orderInfo.setCancelReason(null);
        orderInfo.setPayType(null);
        orderInfo.setCouponId(null);
        orderInfo.setCouponAmount(null);*/
        //保存订单项order_item
        Long orderId = orderInfo.getId();
        orderItemList.forEach(orderItem -> orderItem.setOrderId(orderId));
        orderItemService.saveBatch(orderItemList);

        //删除购物车中选中商品
        client.deleteChecked();
        //返回订单id
        return orderId;
    }

    @Override
    public TradeVo buy(Long skuId) {
        Result<ProductSku> productSkuResult = productFeignClient.getProductList(skuId);
        if (productSkuResult.getCode() != 200) {
            throw new SpzxException(ResultCodeEnum.FEIGN_ERROR);
        }
        ProductSku productSku = productSkuResult.getData();
        Long token = IdUtil.getSnowflake(1, 1).nextId();
        stringRedisTemplate.opsForValue().set("spzx:order:idempotence" + token.toString(), "1", 1, TimeUnit.HOURS);
        OrderItem orderItem = new OrderItem();
        orderItem.setSkuNum(1);
        orderItem.setOrderId(token);
        orderItem.setSkuId(skuId);
        orderItem.setSkuName(productSku.getSkuName());
        orderItem.setThumbImg(productSku.getThumbImg());
        orderItem.setSkuPrice(productSku.getSalePrice());


        TradeVo tradeVo = new TradeVo();
        tradeVo.setOrderItemList(Arrays.asList(orderItem));
        tradeVo.setTotalAmount(orderItem.getSkuPrice());
        return tradeVo;
    }

    @Override
    public PageInfo<OrderInfo> getOrderList(Integer page, Integer limit, Integer orderStatus) {
        Long userId = SpzxAuthInterceptor.threadLocal.get().getId();
        Page<OrderInfo> pages = new Page<>(page, limit);
        LambdaQueryWrapper<OrderInfo> eq = Wrappers.lambdaQuery(OrderInfo.class).eq(OrderInfo::getUserId, userId);
        if (orderStatus != null) {
            eq.eq(OrderInfo::getOrderStatus, orderStatus);
        }
        Page<OrderInfo> mpPage = this.page(pages, eq);
        List<OrderInfo> records = mpPage.getRecords();
        records.forEach(orderInfo -> {
            List<OrderItem> list = orderItemService.list(Wrappers.lambdaQuery(OrderItem.class).eq(OrderItem::getOrderId, orderInfo.getId()));
            orderInfo.setOrderItemList(list);
        });

        //设置给pageHelper
        PageInfo<OrderInfo> pageInfo = new PageInfo<>();
        pageInfo.setPageSize((int) mpPage.getSize());
        pageInfo.setPageNum((int) mpPage.getCurrent());
        pageInfo.setTotal(mpPage.getTotal());
        pageInfo.setList(mpPage.getRecords());
        pageInfo.setPages((int) mpPage.getPages());
        return pageInfo;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderStatusPayed(String orderNo, Integer orderStatus) {
        //更新订单的支付状态
        OrderInfo orderInfo = this.getOne(Wrappers.lambdaQuery(OrderInfo.class).eq(OrderInfo::getOrderNo, orderNo));
         orderInfo.setOrderStatus(orderStatus);
         orderInfo.setPayType(2);
         orderInfo.setPaymentTime(new Date());
         this.updateById(orderInfo);
        //更新库存和销量
        List<OrderItem> orderItems = orderItemService.list(Wrappers.lambdaQuery(OrderItem.class)
                .eq(OrderItem::getOrderId,orderInfo.getId()));

        orderItems.forEach(orderItem -> {
            Long skuId = orderItem.getSkuId();
            Integer skuNum = orderItem.getSkuNum();
            productFeignClient.updateSkuSaleNum(skuId,skuNum);

        });
    }
}
